package org.github.core.spring.restful.json;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import org.github.core.exception.RemoteException;
import org.github.core.spring.restful.Base;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import org.springframework.http.HttpStatus;

import static cn.hutool.core.text.CharSequenceUtil.firstNonBlank;
import static org.github.core.Const.SUB_CODE_DEFAULT;
import static org.github.core.util.JacksonUtil.writeValue;
import static org.springframework.http.HttpStatus.OK;

/**
 * JSON of basic.
 *
 * @author JYD_XL
 * @see java.io.Serializable
 * @see java.util.function.Supplier
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class JSONBase extends Base implements JSON {
    public JSONBase(int code, int subCode, @NotNull String msg) {
        super(code, subCode, msg);
    }

    public JSONBase() {
    }

    /**
     * Generator.
     */
    @NotNull
    public static JSONBase ok() {
        return of(OK, null);
    }

    /**
     * Generator.
     */
    @NotNull
    public static JSONBase of(HttpStatus status, @Nullable String msg) {
        return of(status, SUB_CODE_DEFAULT, msg);
    }

    /**
     * Generator.
     */
    @NotNull
    public static JSONBase of(HttpStatus status, int subCode, @Nullable String msg) {
        return new JSONBase(status.value(), subCode, firstNonBlank(msg, status.name()));
    }

    /**
     * Generator.
     */
    @NotNull
    public static JSONBase of(Base base) {
        return new JSONBase(base.getCode(), base.getSubCode(), base.getMsg());
    }

    @SneakyThrows
    @Override
    public void handle(@NotNull HttpServletRequest req, @NotNull HttpServletResponse res) {
        res.setContentType(mediaType().toString());
        writeValue(this, res.getOutputStream());
    }

    @Override
    @NotNull
    public String get() {
        return super.toString();
    }

    @Override
    public String toString() {
        return get();
    }

    public void throwIfFailed() throws RemoteException {
        if (failure()) throw new RemoteException(this);
    }
}
